/*
 * MainWindow.cpp
 *
 *  Created on: May 13, 2012
 *      Author: walther
 */

#include "MainWindow.h"
#include "Image.h"

#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <iostream>
#include <sstream>
#include <gtk-2.0/gtk/gtklabel.h>
#include <gtk-2.0/gtk/gtkbox.h>
#include <string.h>
#include <glib-2.0/glib/gtypes.h>
#include <gtk-2.0/gtk/gtkwidget.h>
#include <gtk-2.0/gtk/gtkstyle.h>
#include <omp.h>


MainWindow::MainWindow()
{
    _window = build();
    _presenter = new MainWindowPresenter();
}



MainWindow::~MainWindow()
{
    gtk_widget_destroy( _window );
    delete _presenter;
}




void MainWindow::show()
{
    gtk_main();
}



GtkWidget* MainWindow::build()
{
    GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    gtk_container_set_border_width( GTK_CONTAINER (window), 5 );
    gtk_window_set_title( GTK_WINDOW (window), "Raytracing++");
    gtk_window_set_resizable( GTK_WINDOW (window), FALSE ); 
    g_signal_connect( window, "delete-event", G_CALLBACK (cb_deleteWindow), window );
    g_signal_connect( window, "key-press-event", G_CALLBACK( cb_keyPress ), this );

    GtkWidget* mainBox = gtk_vbox_new( FALSE, 2 );
    gtk_container_add( GTK_CONTAINER(window), mainBox );

    GtkWidget* buttonsBox = buildButtonsBox();
    gtk_box_pack_start_defaults( GTK_BOX(mainBox), buttonsBox );
    
    gtk_box_pack_start( GTK_BOX (mainBox), gtk_hseparator_new(), TRUE , TRUE , 5  );
    
    GtkWidget* canvasBox = buildCanvasBox();
    gtk_box_pack_start_defaults( GTK_BOX(mainBox), canvasBox );   
    
    //gtk_box_pack_start( GTK_BOX (mainBox), gtk_hseparator_new(), TRUE , TRUE , 5  );
    
//    GtkWidget* spaceSubdivision = buildSpaceSubdivisionBox();
//    gtk_box_pack_start( GTK_BOX(mainBox), spaceSubdivision, FALSE, FALSE, 2 );

    gtk_box_pack_start( GTK_BOX (mainBox), gtk_hseparator_new(), TRUE , TRUE , 5  );
    
    // Apply button    
    GtkWidget* applyButton = gtk_button_new_with_label( "Apply" );
    gtk_widget_set_size_request( applyButton, 100, 30 );    
    g_signal_connect( applyButton, "clicked", G_CALLBACK( cb_render ), this );
    
    GtkWidget* buttonAlignment = gtk_alignment_new( 1, 1, 0, 0 );
    GtkWidget* buttonHBox = gtk_hbox_new( FALSE, 2 );    
    gtk_box_pack_start( GTK_BOX (buttonHBox), buttonAlignment  , TRUE, TRUE, 2 );
    gtk_box_pack_start( GTK_BOX (buttonHBox), applyButton, FALSE, FALSE, 2 );       
    
    gtk_box_pack_start( GTK_BOX(mainBox), buttonHBox, FALSE, FALSE, 2 );
    
    gtk_widget_show_all( window );

    return window;
}



GtkWidget* MainWindow::buildButtonsBox()
{
    GtkWidget* buttonsBox = gtk_hbox_new(  FALSE, 5 );
    
    // creating button to load a scene
    GtkWidget* loadButton = gtk_button_new_with_label( "Load Scene" );
    gtk_widget_set_size_request( loadButton, 100, 30 );
    gtk_box_pack_start( GTK_BOX(buttonsBox), loadButton, FALSE, FALSE, 2 );
    g_signal_connect( loadButton, "clicked", G_CALLBACK( cb_openScene ), this );    
    
    _fileLabel = gtk_label_new( "" );
    gtk_box_pack_start( GTK_BOX(buttonsBox), _fileLabel, FALSE, FALSE, 2 );
    
    return buttonsBox;
}



GtkWidget* MainWindow::buildCanvasBox()
{
    GtkWidget* canvasBox = gtk_hbox_new( FALSE, 2 );
    
    _rayTraceCanvas = buildRayTraceCanvas();
    _messageBar = gtk_label_new( "" );
    
    GtkWidget* vBox = gtk_vbox_new( FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(vBox), _rayTraceCanvas, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(vBox), _messageBar    , FALSE, FALSE, 2 );    
    gtk_box_pack_start( GTK_BOX(canvasBox), vBox, FALSE, FALSE, 2 );
    
    GtkWidget* vBoxFrames = gtk_vbox_new( FALSE, 2 );
    GtkWidget* toggles = buildToggleBox();
    gtk_box_pack_start( GTK_BOX(vBoxFrames), toggles, FALSE, FALSE, 2 );    
    
    GtkWidget* spaceSubdivision = buildSpaceSubdivisionBox();
    gtk_box_pack_start( GTK_BOX(vBoxFrames), spaceSubdivision, FALSE, FALSE, 2 );    
    
    gtk_box_pack_start( GTK_BOX(canvasBox), vBoxFrames, FALSE, FALSE, 2 );    
    return canvasBox;
}



GtkWidget* MainWindow::buildRayTraceCanvas()
{
    // Create the canvas and set  it's size
    GtkWidget* rayTraceCanvas = gtk_drawing_area_new();
    gtk_drawing_area_size( GTK_DRAWING_AREA(rayTraceCanvas), 400, 450 );

    // OpenGL configuration for the canvas
    GdkGLConfig* glconfig = gdk_gl_config_new_by_mode( static_cast<GdkGLConfigMode>( GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE ) );

    // Define the canvas as capable of rendering OpenGL graphics
    gtk_widget_set_gl_capability( rayTraceCanvas, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE );

    // Connect the signals to the callbacks
    g_signal_connect( rayTraceCanvas, "configure-event", G_CALLBACK( cb_configGLCanvas )    , NULL );
    g_signal_connect( rayTraceCanvas, "expose-event"   , G_CALLBACK( cb_exposeGLCanvas )    , this );
    
    return rayTraceCanvas;
}



GtkWidget* MainWindow::buildToggleBox()
{
    GtkWidget* vbox = gtk_vbox_new( FALSE, 2 );         
    
    _ambientToggle    = gtk_check_button_new_with_label( "Ambient"      );
    _diffuseToggle    = gtk_check_button_new_with_label( "Diffuse"      );
    _specularToggle   = gtk_check_button_new_with_label( "Specular"     );
    _shadowToggle     = gtk_check_button_new_with_label( "Shadow"       );
    _softShadowToggle = gtk_check_button_new_with_label( "Soft Shadow"  );
    _reflectionToggle = gtk_check_button_new_with_label( "Reflection"   );
    _antiAliasToggle  = gtk_check_button_new_with_label( "Antialiasing" );
    
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_ambientToggle)   , TRUE );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_diffuseToggle)   , TRUE );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_specularToggle)  , TRUE );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_shadowToggle)    , TRUE );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_softShadowToggle), TRUE );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_reflectionToggle), TRUE );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_antiAliasToggle) , TRUE );
    
    g_signal_connect( _ambientToggle   , "toggled", G_CALLBACK (cb_toggleButton), this );
    g_signal_connect( _diffuseToggle   , "toggled", G_CALLBACK (cb_toggleButton), this );
    g_signal_connect( _specularToggle  , "toggled", G_CALLBACK (cb_toggleButton), this );
    g_signal_connect( _shadowToggle    , "toggled", G_CALLBACK (cb_toggleButton), this );
    g_signal_connect( _softShadowToggle, "toggled", G_CALLBACK (cb_toggleButton), this );
    g_signal_connect( _reflectionToggle, "toggled", G_CALLBACK (cb_toggleButton), this );
    g_signal_connect( _antiAliasToggle , "toggled", G_CALLBACK (cb_toggleButton), this );
    
    gtk_widget_set_name( _ambientToggle   , "ambientToggle"    );
    gtk_widget_set_name( _diffuseToggle   , "diffuseToggle"    );
    gtk_widget_set_name( _specularToggle  , "specularToggle"   );
    gtk_widget_set_name( _shadowToggle    , "shadowToggle"     );
    gtk_widget_set_name( _softShadowToggle, "softShadowToggle" );
    gtk_widget_set_name( _reflectionToggle, "reflectionToggle" );    
    gtk_widget_set_name( _antiAliasToggle , "antiAliasToggle"  );    
    
    gtk_box_pack_start( GTK_BOX (vbox), _ambientToggle   , FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX (vbox), _diffuseToggle   , FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX (vbox), _specularToggle  , FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX (vbox), _shadowToggle    , FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX (vbox), _softShadowToggle, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX (vbox), _reflectionToggle, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX (vbox), _antiAliasToggle , FALSE, FALSE, 2 );
    
    GtkWidget* effectsFrame = gtk_frame_new( "Effects" );
    gtk_container_add( GTK_CONTAINER(effectsFrame), vbox );
    
    return effectsFrame;
}



GtkWidget* MainWindow::buildSpaceSubdivisionBox()
{
    GtkWidget* vbox = gtk_vbox_new( FALSE, 2 );         
    
    // Toggle
    _regularGridToggle = gtk_check_button_new_with_label( "On" );
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (_regularGridToggle), FALSE );
    g_signal_connect( _regularGridToggle, "toggled", G_CALLBACK (cb_toggleRegularGrid), this );
    gtk_widget_set_name( _regularGridToggle, "regularGridToggle"    );
    
    // Spins    
    GtkWidget* nxHbox = gtk_hbox_new( FALSE, 2 );
    GtkWidget* nyHbox = gtk_hbox_new( FALSE, 2 );
    GtkWidget* nzHbox = gtk_hbox_new( FALSE, 2 );
    GtkWidget* memoryHbox = gtk_hbox_new( FALSE, 2 );
    GtkWidget* spinsVbox = gtk_vbox_new( FALSE, 2 );    
    
    _nxLabel = gtk_label_new( "Nx" );
    _nyLabel = gtk_label_new( "Ny" );
    _nzLabel = gtk_label_new( "Nz" );
    _memoryLabel = gtk_label_new( "Memory" );
    
    _nxSpin  = gtk_spin_button_new_with_range( 1, 1000, 1 );
    _nySpin  = gtk_spin_button_new_with_range( 1, 1000, 1 );
    _nzSpin  = gtk_spin_button_new_with_range( 1, 1000, 1 );
    
    _memorySpin  = gtk_spin_button_new_with_range( 0, 1000, 1 );    
    
    gtk_spin_button_set_value( GTK_SPIN_BUTTON( _nxSpin ), 10 );
    gtk_spin_button_set_value( GTK_SPIN_BUTTON( _nySpin ), 10 );
    gtk_spin_button_set_value( GTK_SPIN_BUTTON( _nzSpin ), 10 );
    
    gtk_spin_button_set_value( GTK_SPIN_BUTTON( _memorySpin ), 10 );
    g_signal_connect( _memorySpin, "value-changed", G_CALLBACK(cb_rayMemoryValueChanged), this );
    
    gtk_box_pack_start( GTK_BOX(nxHbox), _nxSpin, FALSE, FALSE, 2 );    
    gtk_box_pack_start( GTK_BOX(nxHbox), _nxLabel, FALSE, FALSE, 2 );    
    gtk_box_pack_start( GTK_BOX(nyHbox), _nySpin, FALSE, FALSE, 2 );    
    gtk_box_pack_start( GTK_BOX(nyHbox), _nyLabel, FALSE, FALSE, 2 );    
    gtk_box_pack_start( GTK_BOX(nzHbox), _nzSpin, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(nzHbox), _nzLabel, FALSE, FALSE, 2 );    
    
    gtk_box_pack_start( GTK_BOX(memoryHbox), _memorySpin, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(memoryHbox), _memoryLabel, FALSE, FALSE, 2 );   
    
    gtk_box_pack_start( GTK_BOX(spinsVbox), nxHbox, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(spinsVbox), nyHbox, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(spinsVbox), nzHbox, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(spinsVbox), memoryHbox, FALSE, FALSE, 2 );
    
    // Toggle + Spins
    GtkWidget* regularGridVbox = gtk_vbox_new( FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(regularGridVbox), _regularGridToggle, FALSE, FALSE, 2 );
    gtk_box_pack_start( GTK_BOX(regularGridVbox), spinsVbox, FALSE, FALSE, 2 );    
    
    // Rebuild Button
    _rebuildButton = gtk_button_new_with_label( "Rebuild" );
    gtk_widget_set_size_request( _rebuildButton, 100, 30 );
    
    gtk_box_pack_start( GTK_BOX(regularGridVbox), _rebuildButton, FALSE, FALSE, 2 );
    g_signal_connect( _rebuildButton, "clicked", G_CALLBACK( cb_rebuildGrid ), this );
    
    // Regular grid isn't active at first
    bool isActive = false;
    gtk_widget_set_sensitive( _nxSpin, isActive );
    gtk_widget_set_sensitive( _nySpin, isActive );
    gtk_widget_set_sensitive( _nzSpin, isActive );
    gtk_widget_set_sensitive( _memorySpin, isActive );
    
    gtk_widget_set_sensitive( _nxLabel, isActive );
    gtk_widget_set_sensitive( _nyLabel, isActive );
    gtk_widget_set_sensitive( _nzLabel, isActive );
    gtk_widget_set_sensitive( _memoryLabel, isActive );
    
    gtk_widget_set_sensitive( _rebuildButton, isActive );
    
    // Space subdivision
    GtkWidget* frame = gtk_frame_new( "Regular Grid" );
    gtk_box_pack_start( GTK_BOX(vbox), regularGridVbox, FALSE, FALSE, 2 );
    gtk_container_add( GTK_CONTAINER(frame), vbox );
    
    return frame;
}



gboolean MainWindow::cb_exposeGLCanvas( GtkWidget* canvas, GdkEventExpose* event, gpointer user_data )
{
    GdkGLContext *glContext = gtk_widget_get_gl_context( canvas );
    GdkGLDrawable *glDrawable = gtk_widget_get_gl_drawable( canvas );
 
    //tell gtk that we will start calling opengl functions
    if( !gdk_gl_drawable_gl_begin( glDrawable, glContext ) )
    {
        g_assert_not_reached();
    }
    
    //Clear the canvas with black
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
    //Recover access to the image
    MainWindow* window = ( MainWindow* )user_data;
    Image* image = window->_presenter->getImage();
    
    //If Image loaded OK, start drawing
    if( image )
    {
        glBegin( GL_POINTS );
            int width = imgGetWidth( image );
            int height = imgGetHeight( image );

            for (int w = 0; w < width; ++w)
            {
                for (int h = 0; h < height; ++h)
                {
                    float r,g,b;
                    imgGetPixel3f( image, w, h, &r, &g, &b );
                    glColor3f( r,g,b );
                    glVertex2i( w, h );
                }
            }
        glEnd();
    }
    
    //Update image
    gdk_gl_drawable_swap_buffers (glDrawable);
    
    //Tell GTK we stopped messing with OpenGL
    gdk_gl_drawable_gl_end( glDrawable );
    
    //everything went fine
    return TRUE;
}



gboolean MainWindow::cb_configGLCanvas( GtkWidget* canvas, GdkEventConfigure* event, gpointer user_data )
{
    GdkGLContext *glContext = gtk_widget_get_gl_context( canvas );
    GdkGLDrawable *glDrawable = gtk_widget_get_gl_drawable( canvas );

    // start opengl commands
    if( !gdk_gl_drawable_gl_begin( glDrawable, glContext ) )
    {
        g_assert_not_reached();
    }

    glLoadIdentity();
    glViewport( 0, 0, canvas->allocation.width, canvas->allocation.height );
    glMatrixMode( GL_PROJECTION );
    glOrtho ( 0, canvas->allocation.width, 0, canvas->allocation.height, -10, 10 );

    // end opengl commands
    gdk_gl_drawable_gl_end( glDrawable );

    return true;
}



void MainWindow::cb_openScene( GtkWidget* button, gpointer user_data )
{
    GtkWidget* fileChooser;
    gchar* filepath = 0;
    MainWindow* window = (MainWindow*) user_data;

    fileChooser = gtk_file_chooser_dialog_new("Abrir Arquivo",
                                               GTK_WINDOW (window->_window),
                                               GTK_FILE_CHOOSER_ACTION_OPEN,
                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                               GTK_STOCK_OPEN, GTK_RESPONSE_OK,
                                               NULL);

    GtkFileFilter* filter = gtk_file_filter_new();
    gtk_file_filter_set_name( GTK_FILE_FILTER (filter), "(*.rt4, *.RT4)");
    gtk_file_filter_add_pattern( GTK_FILE_FILTER (filter), "*.rt4" );
    gtk_file_filter_add_pattern( GTK_FILE_FILTER (filter), "*.RT4" );
    gtk_file_chooser_add_filter( GTK_FILE_CHOOSER (fileChooser), GTK_FILE_FILTER (filter) );

    if (gtk_dialog_run( GTK_DIALOG (fileChooser) ) == GTK_RESPONSE_OK)
    {
        filepath = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER (fileChooser) );

        if (!window->_presenter->buildScene( filepath ))
        {
            std::string message = "Error loading file";
            gtk_label_set_text( GTK_LABEL (window->_fileLabel), message.c_str()  ); 
        }
        else
        {
            // Rebuild grid if active
            window->cb_toggleRegularGrid( GTK_TOGGLE_BUTTON(window->_regularGridToggle), user_data );
            
            // Sets filename label
            std::string strFilePath = filepath;
            size_t pos = strFilePath.find_last_of( "/\\" );
            
            if (pos != std::string::npos)
            {
                std::string filename = strFilePath.substr( pos + 1 );
                gtk_label_set_text( GTK_LABEL (window->_fileLabel), filename.c_str() );
            }
            else
            {
                gtk_label_set_text( GTK_LABEL (window->_fileLabel), filepath );
            }
            
        }

        gtk_label_set_label( GTK_LABEL(window->_messageBar), "Created by Eliana Goldner and Walther Maciel" );
        gtk_widget_queue_draw( window->_rayTraceCanvas );
        
        g_free( filepath );
    }

    // Define efeitos ativos na cena
    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_ambientToggle)))
        window->_presenter->toggleAmbient( true );
    else
        window->_presenter->toggleAmbient( false );

    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_diffuseToggle)))
        window->_presenter->toggleDiffuse( true );
    else
        window->_presenter->toggleDiffuse( false );

    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_specularToggle)))
        window->_presenter->toggleSpecular( true );
    else
        window->_presenter->toggleSpecular( false );

    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_shadowToggle)))
        window->_presenter->toggleShadow( true );
    else
        window->_presenter->toggleShadow( false );

    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_softShadowToggle)))
        window->_presenter->toggleSoftShadow( true );
    else
        window->_presenter->toggleSoftShadow( false );

    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_reflectionToggle)))
        window->_presenter->toggleReflection( true );
    else
        window->_presenter->toggleReflection( false );

    if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (window->_antiAliasToggle)))
        window->_presenter->toggleAntiAlias( true );
    else
        window->_presenter->toggleAntiAlias( false );
    
    gtk_widget_destroy( fileChooser );
}



void MainWindow::cb_render( GtkWidget* button, gpointer user_data )
{
    MainWindow* window = (MainWindow*)user_data;
    
    double begin = omp_get_wtime();
    window->_presenter->renderScene();    
    double end = omp_get_wtime();
       
    if (!window->_presenter->getImage())
        return;
    
    int width  = imgGetWidth( window->_presenter->getImage() );
    int heigth = imgGetHeight( window->_presenter->getImage()  );

    gtk_drawing_area_size( GTK_DRAWING_AREA (window->_rayTraceCanvas) , width, heigth );
    gtk_window_resize( GTK_WINDOW (window->_window), width, heigth );            
    
    double elapsed = end - begin;
    char message[128];
    
    sprintf( message, "Time elapsed: %.3lf seconds.", elapsed );
    
    gtk_label_set_label( GTK_LABEL(window->_messageBar), message );
}



gboolean MainWindow::cb_deleteWindow( GtkWidget* widget, GdkEvent* event, gpointer data )
{
    gtk_main_quit();

    return TRUE;
}



void MainWindow::cb_toggleButton( GtkToggleButton* togglebutton, gpointer user_data )
{
    MainWindow* window = (MainWindow*) user_data;    
    const gchar* name = gtk_widget_get_name( GTK_WIDGET (togglebutton) );
    
    if (strcmp( name, "ambientToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleAmbient( true );
        else
            window->_presenter->toggleAmbient( false );
    }
    else if (strcmp( name, "diffuseToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleDiffuse( true );
        else
            window->_presenter->toggleDiffuse( false );
    }
    else if (strcmp( name, "specularToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleSpecular( true );
        else
            window->_presenter->toggleSpecular( false );
    }
    else if (strcmp( name, "shadowToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleShadow( true );
        else
            window->_presenter->toggleShadow( false );
    }
    else if (strcmp( name, "softShadowToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleSoftShadow( true );
        else
            window->_presenter->toggleSoftShadow( false );
    }
    else if (strcmp( name, "reflectionToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleReflection( true );
        else
            window->_presenter->toggleReflection( false );
    }
    else if (strcmp( name, "antiAliasToggle") == 0)
    {
        if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON (togglebutton)))
            window->_presenter->toggleAntiAlias( true );
        else
            window->_presenter->toggleAntiAlias( false );
    }
}



void MainWindow::cb_toggleRegularGrid( GtkToggleButton* togglebutton, gpointer data )
{
    MainWindow* window = (MainWindow*) data;
    
    gboolean isActive = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(togglebutton) );
    
    gtk_widget_set_sensitive( window->_nxSpin, isActive );
    gtk_widget_set_sensitive( window->_nySpin, isActive );
    gtk_widget_set_sensitive( window->_nzSpin, isActive );
    
    gtk_widget_set_sensitive( window->_nxLabel, isActive );
    gtk_widget_set_sensitive( window->_nyLabel, isActive );
    gtk_widget_set_sensitive( window->_nzLabel, isActive );
    
    gtk_widget_set_sensitive( window->_memoryLabel, isActive );
    gtk_widget_set_sensitive( window->_memorySpin, isActive );
    
    gtk_widget_set_sensitive( window->_rebuildButton, isActive );
    
    window->_presenter->toggleRegularGrid( isActive );
    
    if (isActive)
    {
        window->cb_rayMemoryValueChanged( GTK_SPIN_BUTTON(window->_memorySpin), data );
        window->cb_rebuildGrid( 0, data );
    }
    else
    {
        window->_presenter->setRayMemorySize( 0 );
    }
}



void MainWindow::cb_rebuildGrid( GtkWidget* button, gpointer data )
{
    MainWindow* window = (MainWindow*) data;
    
    int divX = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(window->_nxSpin) );
    int divY = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(window->_nySpin) );
    int divZ = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(window->_nzSpin) );
    
    window->_presenter->rebuildGrid( divX, divY, divZ );
}



void MainWindow::cb_rayMemoryValueChanged( GtkSpinButton* spinbutton, gpointer data )
{
    MainWindow* window = (MainWindow*) data;
    
    int memorySize = gtk_spin_button_get_value_as_int( spinbutton );
    window->_presenter->setRayMemorySize( memorySize );
}



gboolean MainWindow::cb_keyPress( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
{
    MainWindow* window = (MainWindow*) user_data;
    
    if (window->_presenter->treatKeyPress( event->keyval ))    
        cb_render( 0, user_data );
    
    return FALSE;
}

